#include "EventEngine/Excutor.h"

#define EXCUTORBUFF 32

namespace NTrader
{

Excutor::Excutor()
	:__excutor(nullptr)
	, __started(false)
	, __waitStrategy()
	, __claimStrategy(EXCUTORBUFF, __waitStrategy)
	, __consumed(__waitStrategy, EXCUTORBUFF-1)
	, __buffer(EXCUTORBUFF)
	, __status(WAITING)
	, __nextToRead(0)
{
	__claimStrategy.add_claim_barrier(__consumed);
}


Excutor::~Excutor()
{
}

void Excutor::Excute()
{
	while (__started.load(std::memory_order_acquire))
	{
		const auto available = __claimStrategy.wait_until_published(__nextToRead,std::chrono::microseconds(10));
		if (available < __nextToRead)
		{
			continue;
		}

		//check equal?
		while (__nextToRead <= available)
		{
			Actor_t a = __buffer[__nextToRead];
			__consumed.publish(__nextToRead + EXCUTORBUFF);

			a->Excute();
			__nextToRead++;
		}
	}
}

void Excutor::Post(Actor_t a)
{
	const auto seq = __claimStrategy.claim_one();
	__buffer[seq] = a;
	__claimStrategy.publish(seq);
}

void Excutor::Start()
{
	if (!__excutor)
	{
		__started.store(true, std::memory_order_release);
		__excutor = new std::thread(std::bind(&Excutor::Excute, this));		
	}	
}

void Excutor::Stop()
{
	__started.store(false, std::memory_order_release);

	if (__excutor)
	{
		__excutor->detach();

		delete __excutor;
		__excutor = nullptr;
	}
}

}
